#include <stdio.h>
#include <stdlib.h>
#include "ia1.h"



/*
 Inteligencia Artificial I
 Abril-Julio 2009

 Ejemplo de como utilizar libfia1.so. Hecho por Carlos Castillo.

 Para compilar:

 1. Colocar ia1.h, libfia1.so y ejemplo.c

 2. Compilar de la siguiente forma:
 gcc -lm -L. -lfia1 ejemplo.c -o ejemplo

 3. Para ejecutar:
 LD_LIBRARY_PATH=. ./ejemplo

 Recuerde colocar su numero de carnet en la llamada ia1.
 */
#include "main.h"

reproduce(double child[], double x[10], double y[10]) {

}

randomSelection(double population[20][10], double x[10]) {

}
int geneticAlgorithm() {
	int i;
	double population[20][10];
	double newPopulation[20][10];
	double x[10];
	double y[10];
	double child[10];

	do {
		for (i = 0; i < 20; i++) {
			randomSelection(population, x);
			randomSelection(population, y);

			reproduce(child, x, y);
			if (0) {
				mutate(child);
			}
			copiarEstado(newPopulation[i], child);
		}

	} while (1);

	/*
	 function ~ ~ E N E T I C - A L G O R I T H M (FITNESS-FN) O ~ , an individual
	 ~ O ~ U ~ U ~ returns
	 ~
	 inputs: population, a set of individuals
	 F ITNESS - F N , a function that measures the fitn'essof an individual
	 repeat
	 new-population t empty set
	 loop for i from 1 to S ~ z E ( p o p u ~ a t i odo
	 n)
	 x t R ~ ~ ~ o ~ - S ~ ~ ~ c ~ ~ o ~ ( p o p u l-F N ) i o n ,
	 F ITNESS a t
	 y +- R A N D ~ M - ~ E L E C T I ~ N ( ~ ~ ~ U ~ ~ ~ ~ ~ ~ ,
	 FITNESS-FN)
	 child +- REPRODUCE(X,        y)
	 if (small random probability) then child t M~rT~TE(chi1d)
	 add child to new-population
	 population c new-popu2ation
	 until some individual is fit enough, or enough time has elapsed
	 return the best individual in population, according to F ITNESS -F N
	 function REPRODUCE(X,returns an individual
	 y)
	 inputs: x , y, parent individuals
	 n t LENGTH($)
	 c c random number from 1 to n
	 + 1, n ) )
	 return A P P E N D ( ~ U B S T R I N1, c), ,SUBSTRING(^, c
	 G(X
	 */

}

int shedule() {

}
int vecinosSimulatesAnnealing(double current[10], double vecinos[10]) {

}

double simulatedAnnealing() {
	double current[10];
	double next[10];
	int T;
	int t;
	double deltaE;

	estadoInicial(current);
	for (t = 0; t < INT_MAX; t++) {
		T = shedule(t);
		if (T = 0)
			return evaluar(current);
		vecinosSimulatesAnnealing(current, next);
		deltaE = evaluar(next) - evaluar(current);
		if (deltaE > 0)
			copiarEstado(current, next);
		else if (exp((deltaE / T)))
			copiarEstado(current, next);
	}

	/*
	 function S I M U L A T E D - A N N E A L I N G ( ~ ~ returns a solution state
	 schedule) ~ ~ ~ ~ ~ ,
	 inputs: problem, a problem
	 schedule, a mapping from time to "temperature"
	 local variables: current, a node
	 next, a node
	 T , a "temperature" controlling the probability of downward steps
	 current + MAKE-NoDE(INITIAL-STATE[~~~~~~~])
	 fort+ ltooodo
	 T + schedule[t]
	 if T = 0 then return current
	 next t a randomly selected successor of current
	 AE +V A L U E [ ~ ~ X ~ ]
	 - VALU~[current]
	 if A E > 0 then current +- next
	 else current + next only with probability eAEI
	 */

}

int mio() {
	int i;
	double current[10];
	double vecino[10];

	estadoInicial(current);

	for (i = 0; i < 1000000; i++) {
		vecinosMios(current, vecino);
		if (evaluar(current) < evaluar(vecino)) {
			copiarEstado(current, vecino);
		}
	}

	for (i = 0; i < 10; i++) {

		printf("%f\n", current[i]);

	}

	printf("%f", evaluar(current));
}

double hillClimbing() {
	double current[10];
	double neighbor[10];
	int i = 0;
	estadoInicial(current);
	do {
		/*i++;
		 if(i == 10)
		 break;
		 */

		vecinosHillClimbing(current, neighbor);
		//		printf("Vecino: %1.10f < Actual: %1.10f\n", evaluar(neighbor), evaluar(
		//				current));
		//		imprimirEstado(current);
		if (evaluar(neighbor) <= evaluar(current))
			return evaluar(current);
		copiarEstado(current, neighbor);

	} while (1);

}
int vecinosMios(double estadoActual[10], double vecino[10]) {
	int columna;
	int i;
	srand(Tomar_Tiempo());
	columna = random() % 10;

	for (i = 0; i < 10; i++) {
		if (i == columna)
			vecino[i] = randomFunc();
		else
			vecino[i] = estadoActual[i];
	}

	return 1;

}

int copiarEstado(double current[10], double vecino[10]) {
	int i;
	for (i = 0; i < 10; i++) {
		current[i] = vecino[i];
	}
}

int estadoInicial(double x[10]) {
	int i;

	for (i = 0; i < 10; i++) {

		x[i] = randomFunc();
		//	    	printf("%f\n",x[i]);


	}

}

int neighbors(double estadoActual[]) {
	double e = 0.1;

}

int vecinosSangil(double estadoActual[10]) {
	int i, j, k, l, m, n, o, p, q, r;
	double e = 0.1;
	double posibleV[3][10];
	double current[10];
	double vecino[10];

	for (i = 0; i < 10; i++) {

		if (estadoActual[i] + e < 1)
			posibleV[0][i] = estadoActual[i] + e;
		else
			posibleV[0][i] = -2;

		posibleV[1][i] = estadoActual[i];

		if (estadoActual[i] - e > -1)
			posibleV[2][i] = estadoActual[i] - e;
		else
			posibleV[2][i] = -2;
	}

	for (i = 0; i < 3; i++) {
		if (posibleV[i][0] == -2)
			continue;
		vecino[0] = posibleV[i][0];
		for (j = 0; j < 3; j++) {
			if (posibleV[j][i] == -2)
				continue;
			vecino[1] = posibleV[j][1];
			for (k = 0; k < 3; k++) {
				if (posibleV[k][2] == -2)
					continue;
				vecino[2] = posibleV[k][2];
				for (l = 0; l < 3; l++) {
					if (posibleV[l][3] == -2)
						continue;
					vecino[3] = posibleV[l][3];
					for (m = 0; m < 3; m++) {
						if (posibleV[m][4] == -2)
							continue;
						vecino[4] = posibleV[m][4];
						for (n = 0; n < 3; n++) {
							if (posibleV[n][5] == -2)
								continue;
							vecino[5] = posibleV[n][5];
							for (o = 0; o < 3; o++) {
								if (posibleV[o][6] == -2)
									continue;
								vecino[6] = posibleV[o][6];
								for (p = 0; p < 3; p++) {
									if (posibleV[p][7] == -2)
										continue;
									vecino[7] = posibleV[p][7];
									for (q = 0; q < 3; q++) {
										if (posibleV[q][8] == -2)
											continue;
										vecino[8] = posibleV[q][8];
										for (r = 0; r < 3; r++) {
											if (posibleV[r][9] == -2)
												continue;
											vecino[9] = posibleV[r][9];

											if (evaluar(vecino) > evaluar(
													current))
												copiarEstado(current, vecino);
										}
									}
								}
							}
						}
					}
				}
			}
		}
	}
	printf(" %1.10f \n", evaluar(current));
	copiarEstado(estadoActual,current);
}

int vecinosHillClimbing(double estadoActual[10], double vecino[10]) {
	int i;
	double e = 0.1;
	double current[10];
	double posibleV[10];

	copiarEstado(current, estadoActual);
	copiarEstado(posibleV, estadoActual);

	for (i = 0; i < 10; i++) {
		//	printf("EL valor de i es: %d, y el current antes es: %1.10f",i,current[i]);
		current[i] = current[i] + e;
		//printf(" +e es: %1.10f ",current[i]);

		if (current[i] < 1.0 && evaluar(current) > evaluar(posibleV)) {
			copiarEstado(posibleV, current);
		}

		current[i] = current[i] - 2* e ;
		//printf(" -e es: %1.10f ",current[i]);
		if (current[i] > -1.0 && evaluar(current) > evaluar(posibleV)) {
			copiarEstado(posibleV, current);
		}
		current[i] = current[i] + e;
		//printf("Y termina %1.10f\n",current[i]);
	}

	copiarEstado(vecino, posibleV);

}

int imprimirEstado(double x[10]) {
	int i;
	for (i = 0; i < 10; i++) {
		printf("%1.8f  ", x[i]);
	}
	printf("\n");
}

int main() {
	int i;
	int j = 2;
	double current[10];
	double vecino[10];


	estadoInicial(current);


		vecinosSangil(current);

	return EXIT_SUCCESS;
}

double randomFunc(double j) {

	srand(Tomar_Tiempo());
	double number;
	int entero;
	int isPositivo;

	number = (double) random() / 100000000;
	entero = (int) number;
	isPositivo = random() % 2;

	number = number - entero;
	if (!isPositivo) {
		number = number * -1;
	}

	return number;
}

inline double evaluar(double x[10]) {
	int r;
	double z;
	if ((r = ia1("0234745", x, &z))) {
		fprintf(stderr, "hubo un error: %d\n", r);
		exit(EXIT_FAILURE);
	}
	return z;
}

int Tomar_Tiempo() {
	struct timeval t; /* usado para tomar los tiempos */
	int dt;
	gettimeofday(&t, (struct timezone*) 0);
	dt = (t.tv_sec) * 1000000 + t.tv_usec;
	return dt;
}
